/**
 * 一些特殊逻辑：
 * 1：密码相关
 *    > 新增与变更的密码逻辑，动态添加校验
 *    1.1：如果是变更，那么就给一个32位随机密码，
 *         并且提示：不修改留空即可（其实就是去掉密码的校验）
 *    1.2：如果是新增页面，那么就要添加密码的校验。
 *
 *    > 确认密码，动态校验是否与密码框一致
 *
 * 2：服务器的安全
 *    2.1：如果编号不是特定的，所有的isSuper都给设置成false
 *    2.2: 如果密码不为空，那么需要调用加密方法，将密码加密了，再保存。
 *
 * 3：图片上传：图片上传实际上是保存了一个图片的链接地址。
 *    由于每个头像是唯一的，为了避免头像图片过多，所以每个人只能保留一个图片。
 *    图片的名称是用户编号+固定字符串后加密
 *    3.1：前端逻辑：
 *       3.1.1 点击上传，就将图片上传到一个临时目录。
 *       3.1.2 返回文件名到前台
 *       3.1.3 将这个文件名设置到头像字段。
 *    3.2：后端的逻辑：
 *         为了避免冗余，所有上次文件都保存到一个temp临时目录中，
 *         用户点击提交后，将临时文件复制到正式文件，再服务器上做一个定时任务，开机清除，或者清除72小时前的文件。
 *       3.2.1 发现是上传了一个临时的文件，就将临时文件复制到正式的文件
 *       3.2.2 更新头像这个字段。
 *
 *  4：其他校验
 *     4.1：长度校验
 *     4.2：类型校验：email 电话号码
 *     4.3：正则表达式校验
 *
 *  5: 关于update逻辑
 *     5.1：读取数据的时候，为了省事，就读取了全部的数据，然后传递给前台了。
 *     5.2：在回传给数据库时，有几个输入控件，就返回几个数据进行update，不是全部字段进行update
 *          5.2.1：如果有些字段，例如图片字段，是一个非标准输入控件输入的，那么就做一个隐形输入框，这样也能传回来
 *
 */

import React from 'react';
import { DrawerForm, ProFormText, ProFormSelect, ProFormSwitch } from '@ant-design/pro-form';
import { Form, Col, Row, Upload, Button, Image, message } from 'antd';
import { UploadOutlined } from '@ant-design/icons';
import ImgCrop from 'antd-img-crop';
// 编辑页面公用的props与用来关闭的回调函数
import {
  drawerProps,
  onVisibleChangeHandle,
  isAdd,
  getRegExp,
  getSingleUploadImgProps,
  ArartaUrl,
} from '@/services/Common';

import type { UploadEndPros } from '@/services/Common';

import {
  getAdminById,
  getAdminGroupListOptions,
  updateAdmin,
  existAdminName,
} from '@/services/system/admin';

type AdminEditProps = API.EditPageProps;

const AdminEdit: React.FC<AdminEditProps> = (props: AdminEditProps) => {
  const { visible, id, setVisible, listReload } = props;
  const adminId = id as string;

  const [form] = Form.useForm();

  // 从数据库中得到，用来刷新页面的数据
  const [admin, setAdmin] = React.useState<Partial<API.Admin> | null>(null);
  // 读取取数据库中的数据，并刷新页面
  React.useEffect(() => {
    if (!isAdd(id)) {
      getAdminById(adminId).then((result) => {
        if (result?.data) {
          setAdmin(result.data);
          form.setFieldsValue(result.data);
        }
      });
    } else {
      // 设置一个初始化的数据
      const tempAdmin = {
        enabled: true,
      };
      setAdmin(tempAdmin);
      form.setFieldsValue(tempAdmin);
    }
  }, []);

  // 上传文件
  const [uploading, setUploading] = React.useState(false);
  const uploadProps = getSingleUploadImgProps({
    actionUrl: '/system/admin/uploadAdminAvatar',
    setUploading,
    onUploadEnd: (para: UploadEndPros<string>) => {
      if (para.success) {
        setAdmin({
          ...admin,
          avatar: para.response,
        });
        form.setFieldsValue({ avatar: para.response });
      }
    },
  });

  /**
   * 保存事件
   * @param values 表单传递过来的参数
   */
  const onFinishHandle = async (values: Record<string, any>) => {
    if (!admin) {
      return false;
    }
    const ren: API.ResponseInfo<number> = await updateAdmin({ ...values, adminId });
    if (ren.success) {
      // List要刷新
      listReload();
      message.success('提交成功');
      // 不返回不会关闭弹框
      return true;
    }
    message.success('保存失败');
    return false;
  };

  /**
   * 确认密码校验函数
   * @param _
   * @param value
   */
  const passwordConformValidator = async (_: unknown, value: any) => {
    const adminPassword = form.getFieldValue('adminPassword');

    if (!isAdd(adminId) && !value && !adminPassword) {
      return Promise.resolve();
    }

    if (value !== adminPassword) {
      return Promise.reject(new Error('确认密码必须与密码一致'));
    }
    return Promise.resolve();
  };

  const adminNameValidator = async (_: unknown, value: any) => {
    const result = await existAdminName(value, adminId);
    if (result.data) {
      return Promise.reject(new Error('管理员名称重复'));
    }
    return Promise.resolve();
  };

  return (
    <DrawerForm
      layout="horizontal"
      labelCol={{ span: 4, offset: 0 }}
      form={form}
      title={adminId.length > 0 ? '编辑管理员' : '新增管理员'}
      visible={visible}
      drawerProps={drawerProps}
      onVisibleChange={(visibleProp) => onVisibleChangeHandle(visibleProp, setVisible)}
      onFinish={onFinishHandle}
    >
      <Row>
        <Col span={17}>
          <ProFormText
            width="md"
            name="adminName"
            label="名称"
            placeholder="请输入名称"
            rules={[
              {
                required: true,
              },
              {
                validator: adminNameValidator,
                validateTrigger: ['onBlur'],
              },
            ]}
          />

          <ProFormSelect
            request={() => getAdminGroupListOptions([])}
            width="md"
            name="adminGid"
            label="权限组"
            rules={[
              {
                required: true,
              },
            ]}
            extra="请选择一个权限组，如果没有，请添加权限组"
          />

          <ProFormSwitch
            name="enabled"
            label="是否生效"
            checkedChildren="有效"
            unCheckedChildren="无效"
          />

          <ProFormText.Password
            width="md"
            name="adminPassword"
            label="密码"
            placeholder="请输入密码"
            rules={
              isAdd(adminId)
                ? [
                    {
                      required: true,
                    },
                    { type: 'string', min: 8, max: 50 },
                  ]
                : [{ type: 'string', min: 8, max: 50 }]
            }
            extra="留空表示不更新原有密码"
          />

          <ProFormText.Password
            width="md"
            name="adminPasswordConform"
            dependencies={['adminPassword']}
            label="确认密码"
            rules={
              isAdd(adminId)
                ? [
                    {
                      required: true,
                    },
                    { validator: passwordConformValidator },
                  ]
                : [{ validator: passwordConformValidator }]
            }
            placeholder="请输入确认密码"
          />

          <ProFormText width="md" name="alias" label="昵称" placeholder="请输入昵称" />

          <ProFormText
            width="md"
            name="phone"
            label="手机号"
            placeholder="请输入手机号"
            rules={[{ pattern: getRegExp('mobilePhone'), message: '手机号格式不对' }]}
          />

          <ProFormText
            width="md"
            name="email"
            label="邮箱"
            placeholder="请输入邮箱"
            rules={[{ type: 'email' }]}
          />

          <ProFormText width="md" name="avatar" label="头像" hidden={true} />
        </Col>
        <Col span={6} style={{ textAlign: 'center' }}>
          <Image
            style={{ borderRadius: '50%' }}
            width={150}
            height={150}
            src={admin && admin.avatar ? admin.avatar : ArartaUrl}
            fallback={ArartaUrl}
          />
          <ImgCrop rotate>
            <Upload {...uploadProps}>
              <Button icon={<UploadOutlined />} loading={uploading}>
                更改头像
              </Button>
            </Upload>
          </ImgCrop>
        </Col>
      </Row>
    </DrawerForm>
  );
};

export default AdminEdit;
